# Eliminar variables cols = ["FECHA","VARIACIÓN MENSUAL","VARIACIÓN TRIMESTRAL","VARIACIÓN ANUAL", "DISTRITO"] df_final1 = df_final.drop(columns=cols, errors="ignore") df_final1.info()

# Convierte a número s = df_final1['LATITUD'].astype(str).str.strip() # Convierte a número df_final1['LATITUD'] = pd.to_numeric(s, errors='coerce').astype('Float64') df_final1.info()

# Imputar vulnerabilidad por media por cada distrito # Supongamos que ya tienes cargado tu dataset # dataset_entrenamiento = pd.read_excel("dataset_entrenamiento.xlsx") # Reemplazar los valores "pasados" a NaN (si vienen con otro símbolo, ej. comas) dataset_entrenamiento["VULNERABILIDAD"] = pd.to_numeric( dataset_entrenamiento["VULNERABILIDAD"], errors="coerce" ) # Imputar VULNERABILIDAD con la media por DISTRITO dataset_entrenamiento["VULNERABILIDAD"] = dataset_entrenamiento.groupby("DISTRITO")["VULNERABILIDAD"]\ .transform(lambda x: x.fillna(x.mean())) # Verificar si quedan NaN print(dataset_entrenamiento["VULNERABILIDAD"].isna().sum())

## Imputar todos los valores nulos por la mediana por cada distrito import pandas as pd # Asegurar que todas las columnas numéricas están en formato numérico num_cols = dataset_entrenamiento.select_dtypes(include="number").columns # Para cada columna numérica, imputar los NaN con la mediana del distrito for col in num_cols: dataset_entrenamiento[col] = dataset_entrenamiento.groupby("DISTRITO")[col]\ .transform(lambda x: x.fillna(x.median())) # Verificar si quedan NaN print(dataset_entrenamiento[num_cols].isna().sum())

# ---------------------------- # PARÁMETROS # ---------------------------- start = '2025-07' # horizonte de predicción: inicio end = '2026-06' # horizonte de predicción: fin target_col = 'PRECIO M2' district_col = 'DISTRITO' year_col = 'AÑO' month_col = 'MES_NUM' # Solo lag de 12 meses LAGS = [12] # Lista de distritos (para OHE consistente) distritos = [ 'Arganzuela','Barajas','Carabanchel','Centro','Chamartin','Chamberi','Ciudad Lineal', 'Fuencarral-El Pardo','Hortaleza','Latina','Moncloa-Aravaca','Moratalaz','Puente De Vallecas', 'Retiro','Salamanca','San Blas-Canillejas','Tetuan','Usera','Vicalvaro','Villa De Vallecas', 'Villaverde' ] # --------------------------------------------------------- # 1) Copia histórico y asegura tipos/orden temporal # --------------------------------------------------------- df = dataset_entrenamiento.copy() df[year_col] = df[year_col].astype(int) df[month_col] = df[month_col].astype(int) df['FECHA'] = pd.to_datetime(df[year_col].astype(str) + '-' + df[month_col].astype(str) + '-01') df = df.sort_values([district_col, 'FECHA']).reset_index(drop=True) # --------------------------------------------------------- # 2) Columnas para lag DESDE 'EURIBOR' EN ADELANTE (numéricas) # --------------------------------------------------------- if 'EURIBOR' not in df.columns: raise KeyError("No encuentro la columna 'VARIACIÓN ANUAL' en el DataFrame.") idx_ini = df.columns.get_loc('EURIBOR') candidatas = df.columns[idx_ini:] # desde esa columna hacia la derecha num_cols = df.select_dtypes(include=[np.number]).columns cols_para_lag = [c for c in candidatas if c in num_cols] # mismas columnas y orden # --------------------------------------------------------- # 3) Crea filas FUTURAS por distrito (solo fechas) # --------------------------------------------------------- future_months = pd.period_range(start=start, end=end, freq='M').to_timestamp() future_rows = ( pd.MultiIndex.from_product([distritos, future_months], names=[district_col, 'FECHA']) .to_frame(index=False) ) future_rows[year_col] = future_rows['FECHA'].dt.year future_rows[month_col] = future_rows['FECHA'].dt.month # Añade columnas del histórico con NaN respetando el orden for c in df.columns: if c not in future_rows.columns: future_rows[c] = np.nan future_rows = future_rows[df.columns] # --------------------------------------------------------- # 4) Histórico + futuro y creación del lag12 por DISTRITO # --------------------------------------------------------- full = pd.concat([df, future_rows], ignore_index=True).sort_values([district_col, 'FECHA']) for col in cols_para_lag: full[f'{col}_lag12'] = full.groupby(district_col)[col].shift(12) # --------------------------------------------------------- # 5) Relleno en tramo de predicción con lag12 y columnas estáticas # --------------------------------------------------------- start_dt, end_dt = pd.to_datetime(start), pd.to_datetime(end) mask_future = (full['FECHA'] >= start_dt) & (full['FECHA'] <= end_dt) # columnas estáticas por distrito (ajústalas si tienes más) cols_estaticas = [c for c in ['LATITUD','LONGITUD','SHAPE_AREA'] if c in full.columns] for c in cols_estaticas: full[c] = full.groupby(district_col)[c].ffill().bfill() # Copiar el valor del lag12 si en el futuro está NaN (solo para las columnas a laggear) for c in cols_para_lag: lag12 = f'{c}_lag12' full.loc[mask_future, c] = full.loc[mask_future, c].where( full.loc[mask_future, c].notna(), full.loc[mask_future, lag12] ) # El TARGET debe quedar en NaN en el tramo futuro (lo predecirá el modelo) if target_col in full.columns: full.loc[mask_future, target_col] = np.nan # --------------------------------------------------------- # 6) One-Hot de distritos (prefijo DIST_) y garantía de columnas # --------------------------------------------------------- full = pd.get_dummies(full, columns=[district_col], prefix='DIST', dtype=bool) for d in distritos: colname = f'DIST_{d}' if colname not in full.columns: full[colname] = False # --------------------------------------------------------- # 7) Extrae el DF de PREDICCIÓN y ordena columnas # - Primero TODAS las columnas originales (orden original) # - Después TODAS las columnas lag12 en el mismo orden de sus originales # - Finalmente las columnas OHE (DIST_*) # --------------------------------------------------------- dataset_prediccion = full.loc[mask_future].copy() # columnas originales (del histórico) que están en dataset_prediccion orig_cols = [c for c in df.columns if c in dataset_prediccion.columns] # columnas lag en el mismo orden (solo las existentes) lag_cols = [f'{c}_lag12' for c in orig_cols if f'{c}_lag12' in dataset_prediccion.columns] # columnas OHE dist_cols = sorted([c for c in dataset_prediccion.columns if c.startswith('DIST_')]) # orden final final_cols = orig_cols + lag_cols + dist_cols dataset_prediccion = dataset_prediccion[final_cols] print(dataset_prediccion.shape) dataset_prediccion.head(10)

# ---------------------------- # PARÁMETROS # ---------------------------- start = '2025-07' # horizonte de predicción: inicio end = '2026-06' # horizonte de predicción: fin target_col = 'PRECIO M2' district_col = 'DISTRITO' year_col = 'AÑO' month_col = 'MES_NUM' # Solo lag de 12 meses LAGS = [12] # --------------------------------------------------------- # 1) Copia histórico y asegura tipos/orden temporal # --------------------------------------------------------- df = dataset_entrenamiento.copy() df[year_col] = df[year_col].astype(int) df[month_col] = df[month_col].astype(int) df['FECHA'] = pd.to_datetime( df[year_col].astype(str) + '-' + df[month_col].astype(str) + '-01' ) df = df.sort_values([district_col, 'FECHA']).reset_index(drop=True) # --------------------------------------------------------- # 2) Columnas para lag DESDE 'EURIBOR' EN ADELANTE (numéricas) # --------------------------------------------------------- idx_ini = df.columns.get_loc('EURIBOR') candidatas = df.columns[idx_ini:] # desde esa columna hacia la derecha num_cols = df.select_dtypes(include=[np.number]).columns cols_para_lag = [c for c in candidatas if c in num_cols] # mismas columnas y orden # --------------------------------------------------------- # 3) Crea filas FUTURAS por distrito (solo fechas) # --------------------------------------------------------- future_months = pd.period_range(start=start, end=end, freq='M').to_timestamp() future_rows = ( pd.MultiIndex.from_product([df[district_col].unique(), future_months], names=[district_col, 'FECHA']) .to_frame(index=False) ) future_rows[year_col] = future_rows['FECHA'].dt.year future_rows[month_col] = future_rows['FECHA'].dt.month # Añade columnas del histórico con NaN respetando el orden for c in df.columns: if c not in future_rows.columns: future_rows[c] = np.nan future_rows = future_rows[df.columns] # --------------------------------------------------------- # 4) Histórico + futuro y creación del lag12 por DISTRITO # --------------------------------------------------------- full = pd.concat([df, future_rows], ignore_index=True).sort_values([district_col, 'FECHA']) for col in cols_para_lag: full[f'{col}_lag12'] = full.groupby(district_col)[col].shift(12) # --------------------------------------------------------- # 5) Relleno en tramo de predicción con lag12 y columnas estáticas # --------------------------------------------------------- start_dt, end_dt = pd.to_datetime(start), pd.to_datetime(end) mask_future = (full['FECHA'] >= start_dt) & (full['FECHA'] <= end_dt) # columnas estáticas por distrito cols_estaticas = [c for c in ['LATITUD','LONGITUD','SHAPE_AREA'] if c in full.columns] for c in cols_estaticas: full[c] = full.groupby(district_col)[c].ffill().bfill() # Copiar el valor del lag12 si en el futuro está NaN (solo para las columnas a laggear) for c in cols_para_lag: lag12 = f'{c}_lag12' full.loc[mask_future, c] = full.loc[mask_future, c].where( full.loc[mask_future, c].notna(), full.loc[mask_future, lag12] ) # El TARGET debe quedar en NaN en el tramo futuro (lo predecirá el modelo) if target_col in full.columns: full.loc[mask_future, target_col] = np.nan # --------------------------------------------------------- # 6) Extrae el DF de PREDICCIÓN y ordena columnas # - Primero todas las columnas originales # - Después todas las columnas lag12 en el mismo orden # --------------------------------------------------------- dataset_prediccion = full.loc[mask_future].copy() # columnas originales (del histórico) orig_cols = [c for c in df.columns if c in dataset_prediccion.columns] # columnas lag en el mismo orden lag_cols = [f'{c}_lag12' for c in orig_cols if f'{c}_lag12' in dataset_prediccion.columns] # orden final final_cols = orig_cols + lag_cols dataset_prediccion = dataset_prediccion[final_cols] print(dataset_prediccion.shape) dataset_prediccion.head(10)